let id = 0

/**
 * 大概流程
 *  1. 在 mountComponent 里面 new Watcher(vm, updateComponent, true)，updateComponent本质是vm._update(vm._render())
 *  2. watcher => constructor => this.get()
 *  3. this.get() 里面的 this.getter()，本质是 vm._update(vm._render())
 *  4. 这里将当前的watcher 保存到 Dep.target = watcher，（静态属性就有一个）
 *  5. vm._render() 会读取vm上的数据，触发 defineReactive 里面的 getter (Object.defineProperty了)
 *  6. 就调用了 dep.depend()，本质是 Dep.target.addDep(this)，Dep.target = watcher
 *  7. 回到了 watcher里面的addDep()，watcher在这里去重并记住了 dep
 *  8. 在watcher.addDep(dep)调用了dep.addSub(this)，this就是当前watcher
 *  9. 反过来 dep.addSub(watcher)，Dep也记住了watcher
 *  多对多过程完成！
 *
 */
class Dep {
  constructor() {
    this.id = id++
    this.subs = []
  }

  /**
   * Dep.target 就是 watcher
   * 收集watcher，具体是在 defineReactive 方法的 get 上调用的时候收集
   * 不能放进去重复的watcher
   * 还要让watcher记住当前的dep，多对多的关系
   */
  depend() {
    // this.subs.push(Dep.target)
    // 这样直接放进去会重复，选让watcher记住dep，再返来来记住watcher
    Dep.target.addDep(this)
  }

  addSub(watcher) {
    this.subs.push(watcher)
  }

  // 通过调用watcher.update方法来重新执行渲染函数，本质执行的的watcher.get,
  // 而watcher.get 即是vm._update(vm._render())
  notify() {
    this.subs.forEach(watcher => watcher.update())
  }
}

// Dep.target 就是watcher
Dep.target = null
let stack = []

export function pushTarget(watcher) {
  stack.push(watcher)
  Dep.target = watcher
}
export function popTarget() {
  stack.pop()
  Dep.target = stack[stack.length - 1]
}

export default Dep
